/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package actions

import (
	"sync"
	"gitee.com/tugoer/orivil/mux"
	"gitee.com/tugoer/orivil/config"
)

var redirectData = newRedirectData()

var Redirect = []*mux.Action{
	{
		Method:"GET", Route: "redirect-list", Name: "Get Redirect List",
		Handler: func(ctx *mux.Context) {
			ctx.SendJson(map[string]interface{}{
				"list": redirectData.GetList(),
			})
		},
	},
	{
		Method:"POST", Route: "redirect-list", Name: "Create Redirect List",
		Params:mux.Parameters{
			{
				In:mux.Form,
				Schema:&redirect{},
			},
		},
		Handler: func(ctx *mux.Context) {
			p := &redirect{}
			ctx.WarnParse(p)
			err := redirectData.Add(p)
			if err != nil {
				ctx.ErrWarning(err)
			}
			ctx.MsgSuccess("创建成功", "")
		},
	},
	{
		Method:"PUT", Route: "redirect-list", Name: "Update Redirect List",
		Params:mux.Parameters{
			{
				In:mux.Form,
				Schema:&updateRedirect{},
			},
		},
		Handler: func(ctx *mux.Context) {
			p := &updateRedirect{}
			ctx.WarnParse(p)
			err := redirectData.Update(p.Index, &p.redirect)
			if err != nil {
				ctx.ErrWarning(err)
			}
			ctx.MsgSuccess("修改成功", "")
		},
	},
	{
		Method:"DELETE", Route: "redirect-list", Name: "Delete Redirect List",
		Params:mux.Parameters{
			{
				In:mux.Query,
				Schema:&delRedirect{},
			},
		},
		Handler: func(ctx *mux.Context) {
			p := &delRedirect{}
			ctx.WarnParse(p)
			err := redirectData.Del(p.Index)
			if err != nil {
				ctx.ErrWarning(err)
			}
			ctx.MsgSuccess("删除成功", "")
		},
	},
}

type delRedirect struct {
	Index int `required:"Index 不能为空"`
}

type updateRedirect struct {
	Index int `required:"Index 不能为空"`
	redirect
}

type redirect struct {
	MinID int
	MaxID int
	Url string
}

type redirects struct {
	List []*redirect
	locker sync.RWMutex
	parser *config.Parser
	file string
}

func newRedirectData() *redirects {
	rs := &redirects{
		parser: config.NewJsonParser("data"),
		file: "redirects",
	}
	err := rs.readData()
	if err != nil {
		panic(err)
	}
	return rs
}

func (rs *redirects) saveData() error {
	return rs.parser.Create(rs.file, rs.List)
}

func (rs *redirects) readData() error {
	return rs.parser.ReadOrCreate(rs.file, &rs.List)
}

func (rs *redirects) GetUrl(id int) string {
	rs.locker.RLock()
	defer rs.locker.RUnlock()
	for _, r := range rs.List {
		if r.MinID != 0 && r.MaxID != 0 {
			if r.MinID<=id && id <= r.MaxID {
				return r.Url
			}
		}
	}
	return ""
}

func (rs *redirects) Add(r *redirect) error {
	rs.locker.Lock()
	defer rs.locker.Unlock()
	rs.List = append(rs.List, r)
	return rs.saveData()
}

func (rs *redirects) Del(index int) error {
	rs.locker.Lock()
	defer rs.locker.Unlock()
	if 0 <= index && index < len(rs.List) {
		rs.List = append(rs.List[:index], rs.List[index+1:]...)
	}
	return rs.saveData()
}

func (rs *redirects) Update(index int, r *redirect) error {
	rs.locker.Lock()
	defer rs.locker.Unlock()
	if 0 <= index && index < len(rs.List) {
		rs.List[index] = r
	}
	return rs.saveData()
}

func (rs *redirects) GetList() []*redirect {
	rs.locker.RLock()
	defer rs.locker.RUnlock()
	var list = make([]*redirect, len(rs.List))
	for key, r := range rs.List {
		list[key] = &redirect{
			MinID: r.MinID,
			MaxID: r.MaxID,
			Url: r.Url,
		}
	}
	return list
}
